package com.uu.platform.utils;


import com.uu.platform.result.Result;
import com.uu.platform.result.ResultFactory;
import net.sf.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * @Description: 工具类
 **/
public class CommonUtil {
    /**
     * @Description: 判断小数点后2位的数字的正则表达式
     * @Param: [str]
     **/
    public static boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式
        Matcher match = pattern.matcher(str);
        if (0> Double.parseDouble(str)){
            return false;
        }
        return match.matches();
    }
    /*
     * 将时间转换为时间戳
     */
    public static String dateToStamp(String time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String stamp = "";
        if (!"".equals(time)) {//时间不为空
            try {
                stamp = String.valueOf(sdf.parse(time).getTime());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {    //时间为空
            long current_time = System.currentTimeMillis();  //获取当前时间
            stamp = String.valueOf(current_time);
        }
        return stamp;
    }


    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(long time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time_Date = sdf.format(new Date(time));
        return time_Date;

    }
    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(long time, String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String time_Date = sdf.format(new Date(time));
        return time_Date;

    }
    public static String dateToStamp(String time, String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String stamp = "";
        if (!"".equals(time)) {//时间不为空
            try {
                stamp = String.valueOf(sdf.parse(time).getTime());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {    //时间为空
            long current_time = System.currentTimeMillis();  //获取当前时间
            stamp = String.valueOf(current_time);
        }
        return stamp;
    }


    //格式化时长为 n天N小时N分N秒
    public static Map stampToDuration(long time){
        Map returnMap = new HashMap();

        long secondsTime = time / 1000;
        int days = (int)Math.floor(secondsTime / 86400);
        int hours = (int)Math.floor((secondsTime - (days * 86400)) / 3600);
        int minutes = (int)Math.floor((secondsTime - (days * 86400) - (hours * 3600))  / 60);
        int seconds = (int)Math.floor((secondsTime - (days * 86400) - (hours  * 3600) - (minutes * 60)) % 60);

        returnMap.put("days",days + "");
        returnMap.put("hours",String.format("%02d", hours));
        returnMap.put("minutes",String.format("%02d", minutes));
        returnMap.put("seconds",String.format("%02d", seconds));

        return returnMap;
    }

    //格式化时长为 n天N小时N分N秒
    public static String stampToDurationStr(long time){

        long secondsTime = time / 1000;
        if(secondsTime < 1){
            return "0秒";
        }
        int days = (int)Math.floor(secondsTime / 86400);
        int hours = (int)Math.floor((secondsTime - (days * 86400)) / 3600);
        int minutes = (int)Math.floor((secondsTime - (days * 86400) - (hours * 3600))  / 60);
        int seconds = (int)Math.floor((secondsTime - (days * 86400) - (hours  * 3600) - (minutes * 60)) % 60);

        String returnStr = "";
        if(days > 0){
            returnStr += days + "天";
        }
        if(hours > 0){
            returnStr += hours + "小时";
        }
        if(minutes > 0){
            returnStr += minutes + "分钟";
        }
        if(seconds > 0){
            returnStr += seconds + "秒";
        }
        return  returnStr;
    }

    //格式化金额
    public static String formatMoney(Object money, int decimal){
        String pattern = "########0.";
        for (int i = 0; i < decimal; i++) {
            pattern += "0";
        }
        DecimalFormat decimalFormat = new DecimalFormat(pattern);
        return decimalFormat.format(Double.parseDouble(money.toString()));
    }


    //生成单号
    public static String createSn(String suffix){
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
        long time = System.currentTimeMillis();
        String sn = sdf.format(new Date(time));
        return sn + suffix;
    }

    //生成会员编号
    public static String createMemberSn(){
        long time = System.currentTimeMillis();
        time = time - 1400000000000L;
        return time + "";
    }

    //生成随机数
    public static int random(int min, int max){
        Random random = new Random();
        int s = random.nextInt(max)%(max-min+1) + min;
        return s;
    }

    /**
     * 大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数
     * 此方法中前三位格式有：
     * 13+任意数
     * 145,147,149
     * 15+除4的任意数(不要写^4，这样的话字母也会被认为是正确的)
     * 166
     * 17+3,5,6,7,8
     * 18+任意数
     * 198,199
     */
    public static boolean isMobile(String str) throws PatternSyntaxException {
        // ^ 匹配输入字符串开始的位置
        // \d 匹配一个或多个数字，其中 \ 要转义，所以是 \\d
        // $ 匹配输入字符串结尾的位置
        String regExp = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[3,5,6,7,8])" +
                "|(18[0-9])|(19[8,9]))\\d{8}$";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(str);
        return m.matches();
    }

    public static boolean isEmail(String email){
        if (null==email || "".equals(email)){
            return false;
        }
        String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        Pattern p = Pattern.compile(regEx1);
        Matcher m = p.matcher(email);
        if(m.matches()){
            return true;
        }else{
            return false;
        }
    }


    /**
     * 获取当前网络ip
     * @return
     */
    public static String getIpAddr(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ipAddress = request.getHeader("x-forwarded-for");
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
                //根据网卡取本机配置的IP
                InetAddress inet=null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress= inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
            if(ipAddress.indexOf(",")>0){
                ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    //判断浏览器环境
    public static int getAgent(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String userAgent = request.getHeader("user-agent");
        if (userAgent != null && userAgent.contains("AlipayClient")) {
            return 2;
        }else if (userAgent != null && userAgent.contains("MicroMessenger")) {
            return 1;
        }else{
            return 0;
        }

    }

    //对jsonarray 根据 json 某一键值排序
    public static JSONArray jsonArraySort(JSONArray jsonArray,String key, String sort){

        TreeSet<Map> ts = new TreeSet<Map>(new Comparator<Map>() {
            @Override
            public int compare(Map m1, Map m2) {
                int compareResult = 0;
                if(Pattern.compile("^[-\\+]?[\\d]*$").matcher(m1.get(key).toString()).matches() && Pattern.compile("^[-\\+]?[\\d]*$").matcher(m2.get(key).toString()).matches()){
                    compareResult = Integer.parseInt(m1.get(key).toString()) - Integer.parseInt(m2.get(key).toString());
                }else{
                    compareResult = m1.get(key).toString().compareTo(m2.get(key).toString());
                }
                if(compareResult == 0){ compareResult = 1; }
                if(sort.equals("desc")){
                    compareResult = compareResult * -1;
                }
                return compareResult;
            }
        });

        for (int i = 0; i < jsonArray.size(); i++) {
            ts.add((Map)jsonArray.get(i));
        }

        return JSONArray.fromObject(ts);
    }


    /**
     * 先根遍历序递归删除文件夹
     *
     * @param dirFile 要被删除的文件或者目录
     * @return 删除成功返回true, 否则返回false
     */
    public static boolean deleteFile(File dirFile) {
        // 如果dir对应的文件不存在，则退出
        if (!dirFile.exists()) {
            return false;
        }

        if (dirFile.isFile()) {
            return dirFile.delete();
        } else {

            for (File file : dirFile.listFiles()) {
                deleteFile(file);
            }
        }

        return dirFile.delete();
    }


    //base64编码
    public static String base64Encode(String s) throws UnsupportedEncodingException {
        Base64.Encoder encoder = Base64.getEncoder();
        final byte[] textByte = s.getBytes("UTF-8");
        return encoder.encodeToString(textByte);
    }
    //base64解码
    public static String base64Decode(String s) throws UnsupportedEncodingException {
        Base64.Decoder decoder = Base64.getDecoder();
        return new String(decoder.decode(s), "UTF-8");
    }


    public static String MD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        byte[] var4 = array;
        int var5 = array.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            byte item = var4[var6];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }

    public static String HMACSHA256(String data, String key) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        byte[] var6 = array;
        int var7 = array.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            byte item = var6[var8];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }

    public static String makeSign(Map<String, String> data, String key, String signType) {
        Set<String> keySet = data.keySet();
        String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        String[] var6 = keyArray;
        int var7 = keyArray.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            String k = var6[var8];
            if (!k.equals("sign") && ((String)data.get(k)).trim().length() > 0) {
                sb.append(k).append("=").append(((String)data.get(k)).trim()).append("&");
            }
        }
        sb.append("key=").append(key);
        if ("MD5".equals(signType)) {
            try {
                return MD5(sb.toString()).toUpperCase();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if ("HMACSHA256".equals(signType)) {
            try {
                return HMACSHA256(sb.toString(), key);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return "";
        }

        return "";
    }

    public static Result checkSign(Map<String, String> data, String key, String signType){
        long nowTime = System.currentTimeMillis();
        if(!data.containsKey("nonce_str") || StringUtils.isBlank(data.get("nonce_str"))){
            return ResultFactory.buildFailResult("缺少随机字符串");
        }
        if(!data.containsKey("timestamp") || StringUtils.isBlank(data.get("timestamp"))){
            return ResultFactory.buildFailResult("缺少时间戳");
        }
        if( nowTime > (Long.parseLong(data.get("timestamp").toString()) + 300000) || nowTime < (Long.parseLong(data.get("timestamp").toString()) - 300000)){
            return ResultFactory.buildFailResult("请求超时");
        }
        if(!data.containsKey("sign") || StringUtils.isBlank(data.get("sign"))){
            return ResultFactory.buildFailResult("缺少签名");
        }
        if(!data.get("sign").equals(CommonUtil.makeSign(data,key,"MD5"))){
            return ResultFactory.buildFailResult("签名错误");
        }
        return ResultFactory.buildSuccessResult(new HashMap());
    }



}
